# -*- coding: utf-8 -*-
"""
@author:xuyuntao
@time:2021/1/14:18:14
@email:xuyuntao@189.cn
"""
import numpy
import numpy.fft as nfft
import scipy.signal as scisignal
import csv
import matplotlib.pyplot as plt

class AnalogModulationGenerator(object):
    def __init__(self,freq_carrier:int=3e3,freq_sample:int=14e3,sample_length:int=2*14e3,sound:numpy.ndarray=None):
        """分别为载波频率、采样频率、采样时间长度"""
        self.sampleLength=int(sample_length)
        self.freqSample=int(freq_sample)
        self.timeSeries = numpy.linspace(0,self.sampleLength/self.freqSample,self.sampleLength,dtype=numpy.float64)
        if sound==None:
            freqSound=1e3
            self.sound=numpy.cos(2*numpy.pi*freqSound*self.timeSeries,dtype=numpy.float64)
        else:
            if type(sound) == numpy.ndarray:
                sound = sound.astype(numpy.float64).reshape(-1)
            else:
                raise ValueError
            self.sound = sound/sound.max()   # 对信号做归一化处理，使其最大值为1
        self.freqCarrier=freq_carrier
        self.signal=None
        self.signalFFT = None
        self.freqSeries=None

    def get_AM(self,A=1):
        """生成对sound的AM调制信号，A应大于等于1"""
        if A<1:
            A=1
        self.signal = (A+self.sound) * numpy.cos(2 * numpy.pi * self.freqCarrier * self.timeSeries)
        return self.signal

    def get_DSBSC(self):
        """生成对sound的DSBSC调制信号"""
        self.signal = self.sound * numpy.cos(2 * numpy.pi * self.freqCarrier * self.timeSeries)
        return self.signal

    def get_SSB(self,USB:bool=True):
        """生成对sound的SSB调制信号"""
        if USB:   # 上边带
            self.signal=numpy.real(scisignal.hilbert(self.sound)*\
                             numpy.exp(numpy.complex(0,1)*2*numpy.pi*self.freqCarrier*self.timeSeries))
        else:  # 下边带
            self.signal=self.sound*numpy.cos(2*numpy.pi*self.freqCarrier*self.timeSeries)+\
                        numpy.imag(scisignal.hilbert(self.sound))*\
                        numpy.sin(2*numpy.pi*self.freqCarrier*self.timeSeries)
        return self.signal

    def get_FM(self,Kf=10000):
        """生成对sound的FM调制信号，Kf为调制深度"""
        # numpy.cumsum可进行前缀和
        soundInt=numpy.cumsum(self.sound)/self.freqSample
        self.signal=numpy.cos(2*numpy.pi*self.freqCarrier*self.timeSeries+Kf*soundInt)
        return self.signal

    def get_signal(self,modulation="AM",*args,**kwargs):
        if modulation=="AM":
            self.get_AM(*args,**kwargs)
        elif modulation=="DSBSC":
            self.get_DSBSC(*args,**kwargs)
        elif modulation=="LSB":
            self.get_SSB(False,*args,**kwargs)
        elif modulation=="USB":
            self.get_SSB(True,*args,**kwargs)
        elif modulation=="FM":
            self.get_FM(*args,**kwargs)
        else:
            raise ValueError
        return self.signal

    def get_signal_FFT(self):
        if type(self.signal)==numpy.ndarray:
            self.signalFFT=nfft.fft(self.signal)[0:round(self.sampleLength/2)]
            self.freqSeries = numpy.linspace(0,self.freqSample/2,round(self.sampleLength/2))

        else:
            self.signalFFT=None
            self.freqSeries = None
        return self.freqSeries,self.signalFFT


if __name__=="__main__":
    GAM=AnalogModulationGenerator()
    GAM.get_signal("DSBSC")
    # plt.plot(AMG.sound)
    freqSeries,signalFFT=GAM.get_signal_FFT()
    plt.plot(freqSeries,numpy.abs(signalFFT))
    # plt.yscale("log")
    plt.show()